package org.jackysoft.service.impl;

import java.io.ByteArrayOutputStream;
import java.text.DecimalFormat;
import java.util.Iterator;

import javax.annotation.Resource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.jackysoft.entity.ArmItem;
import org.jackysoft.entity.ArmMonthProductReporter;
import org.jackysoft.entity.Department;
import org.jackysoft.entity.Product;
import org.jackysoft.entity.Role;
import org.jackysoft.entity.User;
import org.jackysoft.report.DataItemType;
import org.jackysoft.report.DataItemUtil;
import org.jackysoft.report.ReportConstant;
import org.jackysoft.report.visitor.ArmItemVisitor;
import org.jackysoft.report.visitor.NewableVisitor;
import org.jackysoft.service.AbstractReportServiceImpl;
import org.jackysoft.service.ArmMonthlyQuicklyReporterService;
import org.jackysoft.util.XmlUtils;
import org.joda.time.DateTime;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
public class ArmMonthlyQuicklyReporterServiceImpl extends
		AbstractReportServiceImpl<ArmMonthProductReporter> implements
		ArmMonthlyQuicklyReporterService {

	/**
	 * 
	 */
	private static final long serialVersionUID = 2601339565348128219L;
	private static final Log logger = LogFactory
			.getLog(ArmMonthlyQuicklyReporterServiceImpl.class);

	private NewableVisitor newableVistor;

	public ArmMonthlyQuicklyReporterServiceImpl() {
		super(ArmMonthProductReporter.class);
	}

	@Override
	public ArmMonthProductReporter get(String id) throws DataAccessException {
		if (id == null)
			return null;
		ArmMonthProductReporter qrpt = super.get(id);
		for (ArmItem ai : qrpt.getArmItems()) {
			newableVistor.visite(ai);
		}
		qrpt.setFreshValue(newableVistor.getValue());
		return qrpt;
	}

	@Override
	public org.w3c.dom.Document w3cDocmentDataSource(String id)
			throws DataAccessException {
		org.w3c.dom.Document w3cdoc = null;

		try {
			w3cdoc = XmlUtils.toW3CDocument(parseToDocument(id));
		} catch (Exception e) {
			e.printStackTrace();
			logger.error(e);
		}

		return w3cdoc;
	}

	@Override
	public void create(ArmMonthProductReporter b) throws DataAccessException {
        
		DateTime now = b.getCreateDate();
		ArmMonthProductReporter lrpt = get(now.getYear(),now.getMonthOfYear()
				,b.getDepartment());
		if (lrpt != null) {
			logger.info("report has exists , not creation bu updation");
			this.update(b);
			return;
		}
		ArmMonthProductReporter last = get(getLast(b.getDepartment()));
		updateAccumulate(b, last);
		super.create(b);
	}

	@Override
	public void update(ArmMonthProductReporter b) throws DataAccessException {
		if(b.isFinished()){
			logger.info("report has finished ,can't for update");
			return;
		}
		ArmMonthProductReporter last = get(getLast(b.getDepartment()));
		updateAccumulate(b, last);
		super.update(b);
	 
	}

	@Override
	@Resource(name = ReportConstant.MonthProductAccumulationVisitor)
	public void setAccumulateVisitor(ArmItemVisitor accumulateVisitor) {
		super.setAccumulateVisitor(accumulateVisitor);
	}

	String getLocalName(User user) {
		return user == null ? "N" : user.getLocalName();
	}

	String getPartName(Department dept) {
		return dept == null ? "N" : dept.getName();
	}

	String getPartName(Role dept) {
		return dept == null ? "N" : dept.getName();
	}

	String getPartId(Department dept) {
		return dept == null ? "N" : dept.getId();
	}

	String getPartId(Role dept) {
		return dept == null ? "N" : dept.getId();
	}

	Document parseToDocument(String id) throws Exception {
		final DataItemUtil du = new DataItemUtil();
		ArmMonthProductReporter arpt = get(id);
		if (arpt == null)
			throw new IllegalArgumentException("参数不正确，或者没有该编号的报表: [" + id + "]");
		Document document = DocumentHelper.createDocument();
		// document.setXMLEncoding("UTF-8");
		Element root = document.addElement("reportor");
		root.addElement("Id").addCDATA(arpt.getId());
		root.addElement("maker").addCDATA(getLocalName(arpt.getMaker()));
		root.addElement("MakerLocalName").addCDATA(
				getLocalName(arpt.getMaker()));
		root.addElement("unitLeader").addCDATA(getLocalName(arpt.getLeader()));
		root.addElement("unitCode").addCDATA(getPartId(arpt.getDepartment()));
		root.addElement("unitName").addCDATA(getPartName(arpt.getDepartment()));
		root.addElement("title").addCDATA(arpt.getTitle());

		DateTime date = arpt.getCreateDate() == null ? DateTime.now() : arpt
				.getCreateDate();
		String ds = date.toString("yyyy-MM-dd");
		root.addElement("dateString").addCDATA(ds);

		root.addElement("showedDateString").addCDATA(ds);
		// 本月产值
		root.addElement("localMonthValue").addCDATA(
				arpt.getLocalMonthValue().toString());
		// 本月总产值
		root.addElement("LocalMonthTotalValue").addCDATA(
				arpt.getLocalMonthTotalValue().toString());
		root.addElement("LastCulumateValue").addCDATA(
				arpt.getLastCulumateValue().toString());
		root.addElement("TotalCumulateValue").addCDATA(
				arpt.getTotalCumulateValue().toString());
		for (ArmItem arm : arpt.getArmItems()) {
			Product host = arm.getHost();
			Element armitem = root.addElement("armitem");
			armitem.addElement("armId").addCDATA(arm.getId());
			armitem.addElement("armCode").addCDATA(host.getCode());
			armitem.addElement("armName").addCDATA(host.getName());
			armitem.addElement("armUnit").addCDATA(host.getPriceUnit());
			armitem.addElement("armPrice").addCDATA(host.getPrice() + "");
			armitem.addElement("armLocalMonthValue").addCDATA(
					du.getDataItemAtom(arm, DataItemType.local).toString());
			armitem.addElement("armLocalMonthPValue").addCDATA(
					du.getDataItemAtom(arm, DataItemType.LocalMonthPValue)
							.toString());
			armitem.addElement("armLocalDelegatePValue").addCDATA(
					du.getDataItemAtom(arm, DataItemType.DelegatedPValid)
							.toString());
			armitem.addElement("armLocalMonthSubmitValue").addCDATA(
					du.getDataItemAtom(arm, DataItemType.submit).toString());
			armitem.addElement("armTotalValue").addCDATA(
					du.getDataItemAccumulation(arm, DataItemType.local)
							.toString());
			Double d = du.getDataItemAccumulation(arm, DataItemType.local)
					* host.getPrice();
			DecimalFormat df = new DecimalFormat("######0.0000");
			armitem.addElement("armTotalPValue").addCDATA(df.format(d));
			armitem.addElement("armMemo").addCDATA(arm.getRemark());
		}

		return document;
	}

	ByteArrayOutputStream armMonthProductReporterXmlds(String id,
			boolean localEmpty) throws Exception {

		ByteArrayOutputStream bout = new ByteArrayOutputStream();
		OutputFormat format = OutputFormat.createPrettyPrint();
		XMLWriter writer = new XMLWriter(bout, format);
		writer.write(parseToDocument(id));
		writer.flush();
		return bout;
	}

	@Resource
	public void setNewableVistor(NewableVisitor newableVistor) {
		this.newableVistor = newableVistor;
	}

	@Override
	public ArmMonthProductReporter get(int year, int month, Department dept)
			throws DataAccessException {
		String hql = HQL(
				"from %s r where year(r.createDate)=%d and month(r.createDate)=%d and r.department.id='%s'",
				table(), year, month, dept);
		Iterator itr = query(hql).iterate();
		return (ArmMonthProductReporter) (itr.hasNext() ? itr.next() : null);
	}

}
